<?php

namespace hth;

use catcher\CatchResponse;
use GuzzleHttp\Exception\RequestException;
use hth\tools\Params;
use think\Exception;
use think\helper\Str;

class Request
{
    protected $key='';

    protected $secret='';

    protected $host='';

    protected $passphrase='';


    protected $nonce='';
    protected $timestamp = '';

    protected $signature='';

    protected $headers=[];

    protected $type='';

    protected $path='';

    protected $data=[];

    protected $options=[];

    protected $platform='';

    protected $version='';

    protected $response_headers=[];

    public function __construct(array $data = [])
    {
//        $this->data['app_key']=$data['app_key'] ?? '2f5bb2157a9f810d';
//        $this->secret= $data['secret'] ?? 'b37682554865a6deb1cc347b0b9ec7da';
//        $this->host=$data['host'] ?? 'http://demoshopapi.ecombird.com';

        $this->data['app_key']=$data['app_key'] ?? '229ca0d8b07558097700a81b487fba97';
        $this->secret= $data['secret'] ?? 'dfb121e320fad7a86be0e1dfa3fbe308';
        $this->host=$data['host'] ?? 'https://api.rishanghainan.com';

        $this->options=$data['options'] ?? [];

        $this->platform=$data['platform'] ?? [];
        $this->data['version']=$data['version'] ?? "1.0";
    }

    /**
     * 认证
     * */
    protected function auth(){
        $this->nonce();
//
        $this->signature();
//
        $this->headers();
//
        $this->options();

    }

    /**
     *
     * */
    protected function nonce(){
        $this->data['timestamp'] = (string) time();
        $this->data['nonce_str']= Str::random(32);
    }

    /**
     * 签名
     * */
    protected function signature(){
        //dd($this->data);
        $this->data = Params::paraFilter($this->data);
        $this->data = Params::argSort($this->data);


        $old = $this->data;

        $this->data = array_filter($this->data);


//        dd($this->data);

        //file_put_contents("aaa.txt","排序前" . PHP_EOL , FILE_APPEND);
        //file_put_contents("aaa.txt",json_encode($this->data , JSON_UNESCAPED_UNICODE) . PHP_EOL,FILE_APPEND);

        //对待签名参数数组排序

        //file_put_contents("aaa.txt","排序后" . PHP_EOL,FILE_APPEND);
        //file_put_contents("aaa.txt",json_encode($this->data , JSON_UNESCAPED_UNICODE) . PHP_EOL,FILE_APPEND);

//        dd($this->data);

        //生成签名结果
        $mysign = Params::buildRequestMysign($this->data,$this->secret);

        //签名结果与签名方式加入请求提交参数组中

        $old['sign'] = $mysign;

//        dd($old);

        $this->data = $old;
        //$this->data =  array_merge($this->data,[$mysign]);
    }

    /**
     *
     * */
    protected function headers(){
        $this->headers=[
            'Content-Type' => 'application/json',
        ];

//        if(!empty($this->key) && !empty($this->secret)) {
//            $this->headers=array_merge($this->headers,[
//                'OK-ACCESS-KEY'=> $this->key,
//                'OK-ACCESS-TIMESTAMP'=>$this->nonce,
//                'OK-ACCESS-PASSPHRASE' =>$this->passphrase,
//                'OK-ACCESS-SIGN' => $this->signature,
//            ]);
//        }
    }

    /**
     *
     * */
    protected function options(){
        if(isset($this->options['headers'])) $this->headers=array_merge($this->headers,$this->options['headers']);

        $this->options['headers']=$this->headers;
        $this->options['timeout'] = $this->options['timeout'] ?? 60;
    }

    /**
     *
     * */
    protected function send(){
        $client = new \GuzzleHttp\Client([
            'headers'=>[
                'Connection' => 'close', // 关闭 Keep-Alive
            ]
        ]);

        $url=$this->host.$this->path;

        if(!empty($this->data)) {
            if($this->type=='GET') {
                $url.='?'.http_build_query($this->data);
            }else{
                $this->options['body']=json_encode($this->data);
            }
        }
//        print_r($this->options);
//        die;
        $response = $client->request($this->type, $url,$this->options);

        $this->response_headers = $response->getHeaders();
        $_getContents = $response->getBody()->getContents();
        $response->getBody()->close();

        return $_getContents;
    }

    /*
     *
     * */
    protected function exec(){
        $this->auth();

        try {
            $result = json_decode($this->send(),true);

//            print_r($result);

            if(200 ==$result['status']) return $result;
//            说明是500开头的 系统错误
//                500	Internal Server Error！程序错误	内部系统错误，请联系开发人员
//                5001	参数错误，请检查参数是否有误！	请查看app_key或者sign是否有传值
//                5002	Appkey不存在，请检查Appkey
//                5003	IP不在白名单内，请添加白名单后再尝试
//                5004	签名错误，请检查签名
//                5005	获取数据超出最大限制，请检查page_size参数
            if(false !== strpos($result['status'],'500'))  throw new Exception("～{$result['status']}网络错误，请联系开发人员～");

            //余额不足也是3004错误，所以必须拦截，防止下游客户看到
            if(strpos($result['message'],'余额不足'))  throw new Exception("～{$result['status']}网络错误，请联系开发人员～");

            //if('账户余额不足，请充值后再来尝试！' === $result['msg'])  throw new Exception("～{$result['code']}网络错误，请联系开发人员～");

            //如果有其他错误，继续拦截
            ///----
            throw new Exception($result['message']);
        }catch (RequestException $e){
            if(empty($e->getResponse()) || $e->getResponse()==null)
                throw new Exception('接口请求失败，没有返回值');

            if(method_exists($e->getResponse(),'getBody')){
                $contents=$e->getResponse()->getBody()->getContents();

                $temp=json_decode($contents,true);
                if(!empty($temp)) {
                    $temp['_method']=$this->type;
                    $temp['_url']=$this->host.$this->path;
                }else{
                    $temp['_message']=$e->getMessage();
                }
            }else{
                $temp['_message']=$e->getMessage();
            }

            $temp['_httpcode']=$e->getCode();

//            throw new Exception(json_encode($temp));
//            throw new Exception($e->getMessage());
            throw new Exception('系统网络错误');
        }
    }

    /**
     * Get Response Headers
     * */
    public function getResponseHeaders(){
        return $this->response_headers;
    }
}